package com.gitee.wsl.collections.set

/**
 * Decorates a `Map` to obtain `Set` behavior.
 *
 *
 * This class is used to create a `Set` with the same properties as
 * the key set of any map. Thus, a ReferenceSet can be created by wrapping a
 * `ReferenceMap` in an instance of this class.
 *
 *
 *
 * Most map implementation can be used to create a set by passing in dummy values.
 * Exceptions include `BidiMap` implementations, as they require unique values.
 *
 *
 * @param <E> the type of the elements in this set
 * @param <V> the dummy value type in this map
 * @since 3.1
</V></E> */
class MapBackedSet<E, V> private constructor(
    private val map: MutableMap<E, in V?>,
    /** The dummyValue to use  */
    private val dummyValue: V?,
) : MutableSet<E> {
    /** The map being used as the backing store  */
    //private val map: MutableMap<E, in V>

    /**
     * Constructor that wraps (not copies).
     *
     * @param map  the map to decorate, must not be null
     * @param dummyValue  the dummy value to use
     * @throws NullPointerException if map is null
     */

    override fun add(element: E): Boolean {
        val size: Int = map.size
        map.put(element, dummyValue)
        return map.size != size
    }

    override fun addAll(elements: Collection< E>): Boolean {
        val size: Int = map.size
        for (e in elements) {
            map.put(e, dummyValue)
        }
        return map.size != size
    }

     override fun clear() {
        map.clear()
    }

     override fun contains(element:E): Boolean {
        return map.containsKey(element)
    }

     override fun containsAll(elements: Collection<E>): Boolean {
        return map.keys.containsAll(elements)
    }

    override fun equals(other: Any?): Boolean {
        return map.keys.equals(other)
    }

    override fun hashCode(): Int {
        return map.keys.hashCode()
    }

     override fun isEmpty(): Boolean {
        return map.isEmpty()
    }

     override fun iterator(): MutableIterator<E> {
        return map.keys.iterator()
    }

     override fun remove(element: E): Boolean {
        val size: Int = map.size
        map.remove(element)
        return map.size != size
    }

     override fun removeAll(elements: Collection<E>): Boolean {
        return map.keys.removeAll(elements)
    }

    /**
     * @since 4.4
     */
//     fun removeIf(filter: Predicate<in E>): Boolean {
//        return map.keys.removeIf(filter)
//    }

     override fun retainAll(elements: Collection<E>): Boolean {
        return map.keys.retainAll(elements)
    }

    override val size: Int
        get() = map.size

//
//     override fun toArray(): Array<Any?> {
//        return map.keySet().toArray()
//    }
//
//     override fun <T> toArray(array: Array<T?>?): Array<T?> {
//        return map.keySet().toArray(array)
//    }

    companion object {

        /**
         * Factory method to create a set from a map.
         *
         * @param <E> the element type
         * @param <V> the dummy value type in the map
         * @param map  the map to decorate, must not be null
         * @return a new map backed set
         * @throws NullPointerException if map is null
         * @since 4.0
        </V></E> */
        fun <E, V> mapBackedSet(map: Map<E, V>): MapBackedSet<E, V> {
            return mapBackedSet(map, null)
        }

        /**
         * Factory method to create a set from a map.
         *
         * @param <E> the element type
         * @param <V> the dummy value type in the map
         * @param map  the map to decorate, must not be null
         * @param dummyValue  the dummy value to use
         * @return a new map backed set
         * @throws NullPointerException if map is null
         * @since 4.0
        </V></E> */
        fun <E, V> mapBackedSet(map: Map<E, V>, dummyValue: V?): MapBackedSet<E, V> {
            return MapBackedSet(map.toMutableMap(), dummyValue)
        }
    }
}
